<?php
// view_visit_log.php - 网站访问日志查看器

require_once 'db_config.php'; // 引入数据库配置

define('ITEMS_PER_PAGE_VISIT', 20); // 每页显示的访问日志条目数量

// 从 GET 参数获取过滤器
$ipFilter = isset($_GET['ip']) ? htmlspecialchars(trim($_GET['ip'])) : '';
$hostFilter = isset($_GET['host']) ? htmlspecialchars(trim($_GET['host'])) : '';
$deviceTypeFilter = isset($_GET['device_type']) ? htmlspecialchars(trim($_GET['device_type'])) : '';
$browserFilter = isset($_GET['browser']) ? htmlspecialchars(trim($_GET['browser'])) : '';
$osFilter = isset($_GET['os']) ? htmlspecialchars(trim($_GET['os'])) : '';
$startDate = isset($_GET['start_date']) ? htmlspecialchars($_GET['start_date']) : '';
$endDate = isset($_GET['end_date']) ? htmlspecialchars($_GET['end_date']) : '';
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($currentPage < 1) $currentPage = 1;

$visitLogs = [];
$totalVisitLogs = 0;
$totalPages = 1;

$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
    die("MySQL 连接失败: " . $conn->connect_error);
}

// 获取筛选器下拉框的选项（从数据库中获取所有不重复的值）
function getDistinctValues($conn, $columnName) {
    $values = [];
    $sql = "SELECT DISTINCT " . $columnName . " FROM visit_log WHERE " . $columnName . " IS NOT NULL AND " . $columnName . " != '' ORDER BY " . $columnName . " ASC";
    $result = $conn->query($sql);
    if ($result) {
        while ($row = $result->fetch_row()) {
            $values[] = $row[0];
        }
    }
    return $values;
}

$distinctDeviceTypes = getDistinctValues($conn, 'device_type');
$distinctBrowsers = getDistinctValues($conn, 'browser');
$distinctOS = getDistinctValues($conn, 'os');


// 构建 WHERE 子句用于过滤
$whereClauses = []; // Correct variable name initialization
$params = [];
$paramTypes = "";

if (!empty($ipFilter)) {
    $whereClauses[] = "ip_address LIKE ?";
    $params[] = "%" . $ipFilter . "%";
    $paramTypes .= "s";
}
if (!empty($hostFilter)) {
    $whereClauses[] = "host LIKE ?";
    $params[] = "%" . $hostFilter . "%";
    $paramTypes .= "s";
}
if (!empty($deviceTypeFilter)) {
    $whereClauses[] = "device_type = ?";
    $params[] = $deviceTypeFilter;
    $paramTypes .= "s";
}
if (!empty($browserFilter)) {
    $whereClauses[] = "browser = ?";
    $params[] = $browserFilter;
    $paramTypes .= "s";
}
if (!empty($osFilter)) {
    $whereClauses[] = "os = ?";
    $params[] = $osFilter;
    $paramTypes .= "s";
}
if (!empty($startDate)) {
    $whereClauses[] = "visit_time >= ?";
    $params[] = $startDate . " 00:00:00";
    $paramTypes .= "s";
}
if (!empty($endDate)) {
    $whereClauses[] = "visit_time <= ?";
    $params[] = $endDate . " 23:59:59";
    $paramTypes .= "s";
}

$whereSql = "";
if (!empty($whereClauses)) { // Correct variable name here
    $whereSql = " WHERE " . implode(" AND ", $whereClauses); // Correct variable name here
}

// 获取总记录数用于分页
$countSql = "SELECT COUNT(*) FROM visit_log" . $whereSql;
$stmtCount = $conn->prepare($countSql);

if (!empty($params)) {
    @call_user_func_array([$stmtCount, 'bind_param'], array_merge([$paramTypes], refValues($params)));
}
$stmtCount->execute();
$stmtCount->bind_result($totalVisitLogs);
$stmtCount->fetch();
$stmtCount->close();

$totalPages = ceil($totalVisitLogs / ITEMS_PER_PAGE_VISIT);
$offset = ($currentPage - 1) * ITEMS_PER_PAGE_VISIT;

// 获取实际的访问日志数据
$sql = "SELECT id, ip_address, host, visit_time, request_uri, request_method, device_type, browser, os, country, city, user_agent, referer, query_string, x_forwarded_for, accept_lang, http_connection, http_accept, http_accept_encoding, http_accept_charset, server_protocol, server_port, server_name, content_type, content_length, script_name, request_time_float, request_time, is_https, mac_address, isp, created_at FROM visit_log"
    . $whereSql . " ORDER BY visit_time DESC LIMIT ?, ?";
$stmt = $conn->prepare($sql);

$mainQueryParams = $params;
$mainParamTypes = $paramTypes;

$mainParamTypes .= "ii"; // Add types for LIMIT and OFFSET
$mainQueryParams[] = $offset;
$mainQueryParams[] = ITEMS_PER_PAGE_VISIT;

if (!empty($mainQueryParams)) {
    @call_user_func_array([$stmt, 'bind_param'], array_merge([$mainParamTypes], refValues($mainQueryParams)));
}

$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    $visitLogs[] = $row;
}
$stmt->close();
$conn->close();

// 辅助函数，用于 call_user_func_array 绑定参数时需要引用
function refValues($arr){
    if (strnatcmp(phpversion(),'5.3') >= 0) // PHP 5.3+ needs to be passed by reference
    {
        $refs = array();
        foreach($arr as $key => $value)
            $refs[$key] = &$arr[$key];
        return $refs;
    }
    return $arr;
}

?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网站访问日志</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
        .container { max-width: 1600px; /* 增加最大宽度 */ margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { color: #0056b3; }
        .back-link { margin-bottom: 20px; text-align: left; }
        .back-link a { color: #007bff; text-decoration: none; }
        .back-link a:hover { text-decoration: underline; }

        /* 筛选表单样式优化 */
        .filter-form {
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f9f9f9;
            display: flex; /* 使用 Flexbox */
            flex-wrap: wrap; /* 允许换行 */
            gap: 15px; /* 增加间距 */
            align-items: flex-end; /* 底部对齐 */
        }
        .filter-form div {
            flex: 1; /* 弹性伸缩 */
            min-width: 150px; /* 最小宽度，防止太窄 */
        }
        .filter-form label {
            font-weight: bold;
            margin-bottom: 5px;
            display: block;
            color: #555;
        }
        .filter-form input[type="date"],
        .filter-form input[type="text"],
        .filter-form select { /* 增加 select 样式 */
            width: 100%;
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        .filter-form button {
            padding: 8px 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            min-width: 80px; /* 按钮最小宽度 */
        }
        .filter-form button:hover {
            background-color: #0056b3;
        }

        .log-table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        .log-table th, .log-table td { border: 1px solid #ddd; padding: 10px; text-align: left; vertical-align: top; }
        .log-table th { background-color: #f2f2f2; font-weight: bold; }
        .log-table tr:nth-child(even) { background-color: #f9f9f9; }
        /* 访问日志表不需要成功/失败颜色，但可以为某些字段添加特定样式 */
        .log-table td.long-text { word-break: break-all; } /* 确保长文本换行 */

        .details-popup {
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0,0,0,0.4);
        }
        .details-popup-content {
            background-color: #fefefe;
            margin: 5% auto; /* 调整垂直居中 */
            padding: 20px;
            border: 1px solid #888;
            width: 90%; /* 增加宽度 */
            max-width: 900px; /* 增加最大宽度 */
            border-radius: 8px;
            position: relative;
        }
        .details-popup-close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
        }
        .details-popup-close:hover,
        .details-popup-close:focus {
            color: black;
            text-decoration: none;
            cursor: pointer;
        }
        .details-popup pre {
            background-color: #eee;
            padding: 10px;
            border-radius: 4px;
            overflow-x: auto;
            white-space: pre-wrap;
            word-break: break-all;
        }
        .pagination { text-align: center; margin-top: 20px; }
        .pagination a { display: inline-block; padding: 8px 12px; margin: 0 5px; border: 1px solid #007bff; border-radius: 4px; text-decoration: none; color: #007bff; }
        .pagination a:hover { background-color: #e0f2ff; }
        .pagination span { display: inline-block; padding: 8px 12px; margin: 0 5px; background-color: #007bff; color: white; border-radius: 4px; }
    </style>
</head>
<body>
<div class="container">
    <h1>网站访问日志</h1>
    <div class="back-link">
        <p><a href="index.php">← 返回监控面板</a></p>
    </div>

    <div class="filter-form">
        <form action="" method="get" style="display: flex; flex-wrap: wrap; gap: 15px; align-items: flex-end;">
            <div>
                <label for="start_date">开始日期:</label>
                <input type="date" id="start_date" name="start_date" value="<?php echo $startDate; ?>">
            </div>
            <div>
                <label for="end_date">结束日期:</label>
                <input type="date" id="end_date" name="end_date" value="<?php echo $endDate; ?>">
            </div>
            <div>
                <label for="ip">IP 地址:</label>
                <input type="text" id="ip" name="ip" value="<?php echo $ipFilter; ?>" placeholder="例如: 192.168.1.1">
            </div>
            <div>
                <label for="host">主机名:</label>
                <input type="text" id="host" name="host" value="<?php echo $hostFilter; ?>" placeholder="例如: example.com">
            </div>
            <div>
                <label for="device_type">设备类型:</label>
                <select id="device_type" name="device_type">
                    <option value="">所有</option>
                    <?php foreach ($distinctDeviceTypes as $type): ?>
                        <option value="<?php echo htmlspecialchars($type); ?>" <?php echo ($deviceTypeFilter === $type) ? 'selected' : ''; ?>>
                            <?php echo htmlspecialchars($type); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div>
                <label for="browser">浏览器:</label>
                <select id="browser" name="browser">
                    <option value="">所有</option>
                    <?php foreach ($distinctBrowsers as $browser): ?>
                        <option value="<?php echo htmlspecialchars($browser); ?>" <?php echo ($browserFilter === $browser) ? 'selected' : ''; ?>>
                            <?php echo htmlspecialchars($browser); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div>
                <label for="os">操作系统:</label>
                <select id="os" name="os">
                    <option value="">所有</option>
                    <?php foreach ($distinctOS as $os): ?>
                        <option value="<?php echo htmlspecialchars($os); ?>" <?php echo ($osFilter === $os) ? 'selected' : ''; ?>>
                            <?php echo htmlspecialchars($os); ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            <button type="submit">筛选</button>
        </form>
    </div>

    <table class="log-table">
        <thead>
        <tr>
            <th>访问时间</th>
            <th>IP 地址</th>
            <th>主机名</th>
            <th>请求 URI</th>
            <th>方法</th>
            <th>设备</th>
            <th>浏览器</th>
            <th>操作系统</th>
            <th>国家/城市</th>
            <th>详情</th>
        </tr>
        </thead>
        <tbody>
        <?php if (empty($visitLogs)): ?>
            <tr><td colspan="10">没有找到符合条件的访问日志记录。</td></tr>
        <?php else: ?>
            <?php foreach ($visitLogs as $log): ?>
                <tr>
                    <td><?php echo htmlspecialchars($log['visit_time']); ?></td>
                    <td><?php echo htmlspecialchars($log['ip_address']); ?></td>
                    <td><?php echo htmlspecialchars($log['host']); ?></td>
                    <td class="long-text"><?php echo htmlspecialchars($log['request_uri']); ?></td>
                    <td><?php echo htmlspecialchars($log['request_method']); ?></td>
                    <td><?php echo htmlspecialchars($log['device_type']); ?></td>
                    <td><?php echo htmlspecialchars($log['browser']); ?></td>
                    <td><?php echo htmlspecialchars($log['os']); ?></td>
                    <td><?php echo htmlspecialchars($log['country'] . '/' . $log['city']); ?></td>
                    <td>
                        <button onclick="showDetails(<?php echo htmlspecialchars(json_encode($log, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); ?>)">查看详情</button>
                    </td>
                </tr>
            <?php endforeach; ?>
        <?php endif; ?>
        </tbody>
    </table>

    <div class="pagination">
        <?php
        // 构建分页链接参数
        $filterParams = "&ip=" . urlencode($ipFilter)
            . "&host=" . urlencode($hostFilter)
            . "&device_type=" . urlencode($deviceTypeFilter)
            . "&browser=" . urlencode($browserFilter)
            . "&os=" . urlencode($osFilter)
            . "&start_date=" . urlencode($startDate)
            . "&end_date=" . urlencode($endDate);

        if ($currentPage > 1): ?>
            <a href="?page=<?php echo $currentPage - 1; ?><?php echo $filterParams; ?>">上一页</a>
        <?php endif; ?>
        <span>页 <?php echo $currentPage; ?> / <?php echo $totalPages; ?></span>
        <?php if ($currentPage < $totalPages): ?>
            <a href="?page=<?php echo $currentPage + 1; ?><?php echo $filterParams; ?>">下一页</a>
        <?php endif; ?>
    </div>
</div>

<div id="detailsPopup" class="details-popup">
    <div class="details-popup-content">
        <span class="details-popup-close" onclick="closeDetails()">&times;</span>
        <h2>访问详情</h2>
        <pre id="detailsContent"></pre>
    </div>
</div>

<script>
    const detailsPopup = document.getElementById('detailsPopup');
    const detailsContent = document.getElementById('detailsContent');

    function showDetails(logData) {
        // 将整个日志数据对象转换为美化的 JSON 字符串
        detailsContent.textContent = JSON.stringify(logData, null, 2);
        detailsPopup.style.display = 'block';
    }

    function closeDetails() {
        detailsPopup.style.display = 'none';
        detailsContent.textContent = '';
    }

    // 点击模态框外部关闭
    window.onclick = function(event) {
        if (event.target == detailsPopup) {
            closeDetails();
        }
    }
</script>
</body>
</html>
